
package com.gcloud.mesh.dcs.service;

import com.gcloud.framework.db.PageResult;
import com.gcloud.mesh.asset.service.IAssetService;
import com.gcloud.mesh.dcs.dao.ModelFactorDao;
import com.gcloud.mesh.dcs.dao.ModelScoreDao;
import com.gcloud.mesh.dcs.entity.ModelScoreEntity;
import com.gcloud.mesh.header.enums.ModelScoreType;
import com.gcloud.mesh.header.enums.ModelType;
import com.gcloud.mesh.header.enums.MonitorMeter;
import com.gcloud.mesh.header.exception.BaseException;
import com.gcloud.mesh.header.exception.ModelErrorCode;
import com.gcloud.mesh.header.msg.asset.ListDatacenterMsg;
import com.gcloud.mesh.header.msg.asset.ListDeviceMsg;
import com.gcloud.mesh.header.msg.dcs.*;
import com.gcloud.mesh.header.vo.asset.DatacenterItemVo;
import com.gcloud.mesh.header.vo.asset.DeviceItemVo;
import com.gcloud.mesh.header.vo.dcs.*;
import com.gcloud.mesh.header.vo.monitor.SampleVo;
import com.gcloud.mesh.monitor.service.StatisticsCheatService;
import com.gcloud.mesh.monitor.service.StatisticsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.DictCode;
import org.jeecg.common.exception.ParamException;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;

@Service
@Slf4j
public class ModelService {

	@Autowired
	private IAssetService assetService;

	@Autowired
	private StatisticsService statsService;

	@Autowired
	private StatisticsCheatService statisticsCheatService;

	@Autowired
	private SchedulerService schedulerService;

	@Autowired
	private ModelFactorDao factorDao;

	@Autowired
	private ModelScoreDao scoreDao;

	@Autowired
	private AppService appService;

	@Autowired
	private SysDictMapper sysDictMapper;
	

	private static final Map<ModelType, List<ModelFactorVo>> MODEL_FACTOR_MAP = new HashMap<>();
	private static final Map<String, String> FACTOR_ID_NAME = new HashMap<>();

	@PostConstruct
	void init() {
		for (ModelType mt : ModelType.values()) {
			this.refreshCachedModelType(mt);
		}
	}

	private void refreshCachedModelType(ModelType mt) {
		List<ModelFactorVo> factors = factorDao.getByModelType(mt, ModelFactorVo.class);
		MODEL_FACTOR_MAP.put(mt, factors);
		log.info("[ModelFactor] caching: {} -> {}", mt.name(), factors);
		for (ModelFactorVo factor : factors) {
			FACTOR_ID_NAME.put(factor.getId(), factor.getFactorName());
		}
	}

	public void setModelFactors(SetModelFactorsMsg msg) throws BaseException {
		ModelType modelType = ModelType.checkAndGet(msg.getModelType());

		if (modelType == null) {
			throw new ParamException(ModelErrorCode.MODEL_TYPE_FORMAT_ERROR);
		}

		List<ModelFactorVo> inputFactors = msg.getFactors();
		List<ModelFactorVo> cachedFactors = MODEL_FACTOR_MAP.get(modelType);
		if (inputFactors == null || inputFactors.size() - cachedFactors.size() != 0) {
			throw new BaseException(ModelErrorCode.FACTORS_INCOMPLETE);
		}
		// this.paramsCheck(inputFactors);

		this.sortFactors(inputFactors);

		// 对比输入的和缓存中的,做好参数校验
		int sum = 0;
		Set<String> set = new HashSet<>();
		for (ModelFactorVo cachedFactor : cachedFactors) {
			set.add(cachedFactor.getId());
		}
//		for (ModelFactorVo inputFactor : inputFactors) {
//			//ModelScoreType.checkAndGet(inputFactor.getScoreType());
//			sum += inputFactor.getEnabled() ? inputFactor.getWeight() : 0;
//			if (set.add(inputFactor.getId())) {
//				throw new BaseException(ModelErrorCode.MODEL_FACTOR_ID_ERROR);
//			}
//		}
//		int sumWeight = 100;
//		if (modelType.getDeviceType() != 3 && sum != sumWeight) {
//			throw new BaseException(ModelErrorCode.WEIGHT_SUM_LESS_THEN_100);
//		}

		synchronized (modelType) {
			this.factorDao.updateBatch(inputFactors.toArray(new ModelFactorVo[] {}));
			this.refreshCachedModelType(modelType);
		}
	}

	// TODO: 不同类型的sample不同的范围要求. id的对应关系找表dcs_models_factor
	// 对参数进行精确的校验，因为注解校验无法精确
	private void paramsCheck(List<ModelFactorVo> factors) throws BaseException {
		for (ModelFactorVo fac : factors) {
			switch (fac.getId()) {
			case "00000000-0000-0000-0001-000000002003":
				Integer scoreSample = fac.getScoreSample();
				if (scoreSample < 0 || scoreSample > 99999) {
					throw new ParamException(null, "评分信息错误");
				}
				break;

			case "00000000-0000-0000-0001-000000002001":
				break;

			default:
				// null
				throw new BaseException("");
			}
		}
	}

	private void sortFactors(List<ModelFactorVo> factors) {
		Collections.sort(factors, new Comparator<ModelFactorVo>() {

			@Override
			public int compare(ModelFactorVo f0, ModelFactorVo f1) {
				return f0.getId().compareTo(f1.getId());
			}

		});
	}

	public List<ModelFactorVo> getModelFactors(GetModelFactorsMsg msg) {
		ModelType modelType = ModelType.checkAndGet(msg.getModelType());
		if (modelType == null) {
			throw new ParamException(ModelErrorCode.MODEL_TYPE_FORMAT_ERROR);
		}
		List<ModelFactorVo> factors = MODEL_FACTOR_MAP.get(modelType);
		for (ModelFactorVo factor : factors) {
			factor.setUnit(MonitorMeter.getByMeter(factor.getFactorType()).getUnit());
			factor.setLayer(MonitorMeter.getByMeter(factor.getFactorType()).getLayer());
			factor.setDiff(factor.getDiff() == null ? 0:factor.getDiff());
		}
		return factors;
	}

	public DetailModelScoreReplyMsg detailModelScore(DetailModelScoreMsg msg) throws BaseException {
		DetailModelScoreReplyMsg res = new DetailModelScoreReplyMsg();
		res.setResourceId(msg.getResourceId());
		ModelType modelType = ModelType.checkAndGet(msg.getModelType());
		GetModelFactorsMsg getmsg = new GetModelFactorsMsg();
		getmsg.setModelType(msg.getModelType());
		List<ModelFactorVo> models = getModelFactors(getmsg);
		if (modelType == null) {
			throw new ParamException(ModelErrorCode.MODEL_TYPE_FORMAT_ERROR);
		}
		res.setFactors(models);
		if (modelType.getDeviceType() == 3) {

			// 先预测，再计算迁移代价
			SchedulerEffectPredictionMsg imagineMsg = new SchedulerEffectPredictionMsg();
			imagineMsg.setAppId(msg.getResourceId());
			imagineMsg.setModelType(modelType.name());
			imagineMsg.setDatacenterId(msg.getDatacenterId());
			SchedulerEffectPredictionVo schedulerEffectPredictionVo = schedulerService
					.schedulerEffectPrediction(imagineMsg);
			Double diff = schedulerEffectPredictionVo.getBusinessRespondDifference();

			Double totalScore = 0.0;
			List<ModelFactorVo> factors = MODEL_FACTOR_MAP.get(modelType);
			for (ModelFactorVo factor : factors) {
				ModelScoreVo vo = new ModelScoreVo();
				double factorValue = 0;
				if (factor.getEnabled()) {

					if (factor.getFactorType().equals("cost.temperature")) {
						factorValue = schedulerEffectPredictionVo.getTemperatureImagine() * diff;
					} else if (factor.getFactorType().equals("cost.load")) {
						factorValue = schedulerEffectPredictionVo.getDistributionBoxVoltageImagine() * diff;
					} else if (factor.getFactorType().equals("cost.power")) {
						factorValue = schedulerEffectPredictionVo.getDatacenterEnergyImagine() * diff;
					} else if (factor.getFactorType().equals("cost.response_time")) {
						factorValue = schedulerEffectPredictionVo.getBusinessRespondImagine() * diff;
					}
																																																																																																																																																																																																																																																																																																																																								
					BigDecimal b = new BigDecimal(factorValue);
					factorValue = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

					double factorScore = this.calculateFactorScoreD(factor, factorValue);
					log.info("[ModelFactor][{}][{}] 因子评分计算：因子={}, 监控值={}, 因子样本值={}, 因子最大值={}, 因子得分={}",
							modelType.name(), imagineMsg.getAppId(), factor.getFactorType(), factorValue,
							factor.getScoreSample(), factor.getEndX(), factorScore);

					totalScore += (factorScore * factor.getWeight() / 100.0);

					vo.setFactorId(factor.getId());
					vo.setFactorName(FACTOR_ID_NAME.get(factor.getId()));
					vo.setScore((int) Math.round(factorScore));
					vo.setLayer(MonitorMeter.getByMeter(factor.getFactorType()).getLayer());
					res.getScores().add(vo);
				}
			}

			res.setTotalScore((int) Math.round(totalScore));
			

			log.info("[ModelFactor][{}][{}] 总分：{}", modelType.name(), imagineMsg.getAppId(), totalScore.intValue());
			return res;
		}
		// ModelScoreEntity score = this.scoreDao.get(modelType,
		// msg.getResourceId(), ModelScoreEntity.class);
		List<ModelScoreEntity> scores = scoreDao.getPageOrderByTime(modelType, msg.getResourceId(),
				ModelScoreEntity.class);
		if (scores == null) {
			return res;
		}
		ModelScoreEntity score = scores.get(0);

		List<ModelFactorVo> factors = MODEL_FACTOR_MAP.get(modelType);
		String[] factorScores = score.getScores().split(",");
		int i = 0;
		for (ModelFactorVo factor : factors) {
			int factorScore = Integer.valueOf(factorScores[i++]);
			if (factorScore < 0) {
				continue;
			}
			ModelScoreVo vo = new ModelScoreVo();
			vo.setFactorId(factor.getId());
			vo.setFactorName(FACTOR_ID_NAME.get(factor.getId()));
			vo.setScore(factorScore);
			res.getScores().add(vo);
		}
		res.setTotalScore(score.getTotalScore());
		//zhangdp判断数据中心是否需要迁移
		boolean needMigrate = needSchedule(msg.getResourceId(), modelType.name(), res.getTotalScore());
		res.setNeedMigrate(needMigrate);
		return res;
	}

	@Scheduled(initialDelay = 30 * 1000, fixedDelay = 60 * 1000)
	void periodCalculateScore() {
		log.info("[ModelFactor][定时刷新资源评分] begin");

		// 遍历模型类型：最优成本、最优设备、空调、UPS，分别从这几个维度开始算分
		for (ModelType mt : ModelType.values()) {
//			if (mt.getDeviceType() == 3) {
//				continue;
//			}
			this.calculateModelTypeScore(mt);
		}

		log.info("[ModelFactor][定时刷新资源评分] end");
	}

	@Scheduled(initialDelay = 30 * 1000, fixedDelay = 60 * 1000 * 5)
	void periodCalculateBestPredict() {
		log.info("[ModelFactor][定时计算最优策略样本] begin");

		// 遍历模型类型：最优成本、最优设备、空调、UPS，分别从这几个维度开始算分
		for (ModelType mt : ModelType.values()) {
			if (mt.getDeviceType() == 7) {
				this.calculateModelTypeBestPredict(mt, false);
			}
		}

		log.info("[ModelFactor][定时计算最优策略样本] end");
	}

	private void calculateModelTypeBestPredict(ModelType mt, boolean updatelessNinty) {
		List<ModelFactorVo> factors = MODEL_FACTOR_MAP.get(mt);

		PageResult<ModelScoreEntity> scores = scoreDao.getPage(mt, 1, 99999, null, null, ModelScoreEntity.class);
		Map<String, List<Integer>> bestFactors = new HashMap<>();
		for (ModelScoreEntity score : scores.getList()) {
			List<String> factorSamples = Arrays.asList(score.getSamples().split(","));
			List<String> factorScores = Arrays.asList(score.getScores().split(","));
			List<String> factorNames = Arrays.asList(score.getFactorNames().split(","));
			List<String> factorValues = Arrays.asList(score.getValues().split(","));

			for (int i = 0; i < factorScores.size(); i++) {
				List<Integer> best = new ArrayList<>();

				if (bestFactors.get(factorNames.get(i)) != null) {
					best = bestFactors.get(factorNames.get(i));
				}
				if (updatelessNinty || Integer.valueOf(factorScores.get(i)) >= 90) {
					// 记录大于90分的因子样本

					//best.add(Integer.valueOf(factorSamples.get(i)));
					best.add(Integer.valueOf(factorValues.get(i)));
				}
				bestFactors.put(factorNames.get(i), best);
			}
		}

		for (ModelFactorVo factor : factors) {
			List<Integer> bestScores = bestFactors.get(factor.getFactorName());
			log.info("[ModelFactorBest] 因子={},优秀样本={}", factor.getFactorName(), bestScores.toString());
			int num = 0;
			if (bestScores != null && bestScores.size() > 0) {
				for (int score : bestScores) {
					num = num + score;
				}
				factor.setScoreBestPredict(num / bestScores.size());
				synchronized (mt) {
					this.factorDao.updateBatchBest(factors.toArray(new ModelFactorVo[] {}));
					this.refreshCachedModelType(mt);
				}
			} else {
				log.info("[ModelFactorBest] 没有优秀样本!");
			}

		}

	}

	private void calculateModelTypeScore(ModelType mt) {
		List<ModelFactorVo> factors = MODEL_FACTOR_MAP.get(mt);

//		// 根据最优模型对应的资源类型，向AssetService拿资源列表进行遍历
//		ListDeviceMsg m = new ListDeviceMsg();
//		m.setType(mt.getDeviceType());
//		List<DeviceItemVo> resources = this.assetService.listDevice(m);
		
		ListDatacenterMsg ldm = new ListDatacenterMsg();
		List<DatacenterItemVo> resources = this.assetService.listDatacenter(ldm);
		
		if (mt.getDeviceType() == 6){
			resources.clear();
			
			ListDeviceMsg m = new ListDeviceMsg();
			m.setType(mt.getDeviceType());
			List<DeviceItemVo> devices = this.assetService.listDevice(m);
			for(DeviceItemVo device : devices){
				DatacenterItemVo vo = new DatacenterItemVo();
				vo.setId(device.getId());
				resources.add(vo);
			}
		}
		if (mt.getDeviceType() == 8){
			resources.clear();
			
			PageAppMsg msg = new PageAppMsg();
			PageResult<AppItemVo> apps = this.appService.page(msg);
			for(AppItemVo app : apps.getList()){
				DatacenterItemVo vo = new DatacenterItemVo();
				vo.setId(app.getId());
				resources.add(vo);
			}
		}
		
		if (mt.getDeviceType() == 3) {
			for (int i = 1; i < 10000; i++) {
				PageAppMsg msg = new PageAppMsg();
				msg.setPageNo(i);
				msg.setPageSize(10);
				PageResult<AppItemVo> apps = appService.page(msg);
				for (AppItemVo app : apps.getList()) {
					DatacenterItemVo item = new DatacenterItemVo();
					item.setId(app.getId());
					resources.add(item);
					if (resources.size() == 0) {
						break;
					}
				}
			}
		}

		Date date = new Date();
		for (DatacenterItemVo resource : resources) {
			this.calculateResourceScore(resource, mt, factors, date);
		}
	}

	/**
	 ** 对单个资源进行算分
	 * 
	 * @param resource
	 * @param mt
	 * @param factors
	 */
	private void calculateResourceScore(DatacenterItemVo resource, ModelType mt, List<ModelFactorVo> factors, Date date) {
		// ModelScoreEntity score = this.scoreDao.get(mt, resource.getId(),
		// ModelScoreEntity.class);

		List<ModelScoreEntity> scoresList = scoreDao.getPageOrderByTime(mt, resource.getId(), ModelScoreEntity.class);
		ModelScoreEntity score = new ModelScoreEntity();
		if (scoresList.size() <= 0) {
			log.debug("[ModelFactor][{}][{}] 原有评分为null", mt.name(), resource.getId());
		} else {
			score = scoresList.get(0);
			log.debug("[ModelFactor][{}][{}] 原有评分为{}：{}", mt.name(), resource.getId(), score.getTotalScore(),
					score.getScores());
		}

		StringBuilder scores = new StringBuilder();
		StringBuilder factorNames = new StringBuilder();
		StringBuilder samples = new StringBuilder();
		StringBuilder weights = new StringBuilder();
		StringBuilder values = new StringBuilder();
		double totalScore = 0;

		// 遍历模型因子，例如温度、湿度、负载等
		if (factors.size() > 0) {

			for (ModelFactorVo factor : factors) {
				int factorScore = 0;
				int factorValue = 0;
				if (factor.getEnabled()) {
					// 向监控拿对应的数据
					factorValue = this.getMeterValue(factor.getFactorType(), resource.getId())
							/ factor.getUnitConversion();
					factorScore = this.calculateFactorScore(factor, factorValue);
					log.info("[ModelFactor][{}][{}] 因子评分计算：因子={}, 监控值={}, 因子样本值={}, 因子最大值={}, 因子得分={}", mt.name(),
							resource.getId(), factor.getFactorType(), factorValue, factor.getScoreSample(),
							factor.getEndX(), factorScore);

					totalScore += (factorScore * factor.getWeight() / 100.0);
				}
				if (scores.length() > 0) {
					scores.append(",");
				}
				if (factorNames.length() > 0) {
					factorNames.append(",");
				}
				if (samples.length() > 0) {
					samples.append(",");
				}
				if (weights.length() > 0) {
					weights.append(",");
				}
				if (values.length() > 0) {
					values.append(",");
				}
				scores.append(factorScore);
				factorNames.append(factor.getFactorName());
				samples.append(factor.getScoreSample());
				weights.append(factor.getWeight());
				values.append(factorValue);
			}

			score = new ModelScoreEntity();
			score.setId(UUID.randomUUID().toString());
			score.setResourceId(resource.getId());
			score.setModelType(mt.name());
			score.setScores(scores.toString());
			score.setTotalScore((int) Math.round(totalScore));
			score.setFactorNames(factorNames.toString());
			score.setSamples(samples.toString());
			score.setValues(values.toString());
			score.setUpdateTime(date);
			this.scoreDao.save(score);
			log.info("[ModelFactor][{}][{}] 新的评分为{}：因子得分:{},权重:{}", mt.name(), resource.getId(), score.getTotalScore(),
					score.getScores(), weights.toString());
		}
	}

	/**
	 ** 根据评分方式，进行算分
	 * 
	 * @param factor
	 * @param value
	 * @return
	 */
	private int calculateFactorScore(ModelFactorVo factor, int value) {
		if (StringUtils.equals(factor.getScoreType(), ModelScoreType.SAMPLE_PERCENTAGE.name())) {
			return SamplePercentageCalculator.calculate(factor, value);
		}
		return 50;
	}

	private double calculateFactorScoreD(ModelFactorVo factor, double value) {
		if (StringUtils.equals(factor.getScoreType(), ModelScoreType.SAMPLE_PERCENTAGE.name())) {
			return SamplePercentageCalculator.calculateD(factor, value);
		}
		return 50;
	}

	private int getMeterValue(String factorType, String resourceId) {
		int res = 0;
		try {
			List<SampleVo> values = this.statisticsCheatService.latestSamples(factorType, resourceId);
			res = values.get(0).getVolume().intValue();
		} catch (Exception e) {

		}
		return res;
	}

	public PageResult<PageModelScoreVo> pageModelScore(PageModelScoreMsg msg) {
		// 还没做name过滤
		if (msg.getModelType() != null && ModelType.checkAndGet(msg.getModelType()) == null) {
			throw new ParamException(ModelErrorCode.MODEL_TYPE_FORMAT_ERROR);
		}
		PageResult<PageModelScoreVo> pageResult = this.scoreDao.getPage(ModelType.checkAndGet(msg.getModelType()),
				msg.getPageNo(), msg.getPageSize(), msg.getDeviceName(), msg.getDatacenterId(), PageModelScoreVo.class);
		if (!msg.getModelType().equals("COST")) {
			for (PageModelScoreVo modelScore : pageResult.getList()) {
				modelScore.setDatacenterName(modelScore.getDatacenterName());
			}
		}
		return pageResult;
	}
	
	
	public PageResult<PageAppModelScoreVo> pageAppModelScore(PageAppModelScoreMsg msg) {
		PageResult<PageAppModelScoreVo> res = new PageResult<PageAppModelScoreVo> ();
		List<PageAppModelScoreVo> resList = new ArrayList<>();
		// 还没做name过滤
		
		//查出应用的分数
		PageModelScoreMsg appmsg = new PageModelScoreMsg();
		appmsg.setPageNo(msg.getPageNo());
		appmsg.setPageSize(msg.getPageSize());
		appmsg.setDeviceName(msg.getDeviceName());
		appmsg.setModelType(ModelType.APP.name());
		PageResult<PageModelScoreVo> appPage = pageModelScore(appmsg);
		for(PageModelScoreVo vo : appPage.getList()) {
			PageAppModelScoreVo resvo = new PageAppModelScoreVo();
			BeanUtils.copyProperties(vo, resvo);
			resList.add(resvo);
		}
		res.setList(resList);
		res.setTotalCount(appPage.getTotalCount());
		return res;
	}

	public PageResult<PageDeviceScoreVo> pageDeviceScore(PageModelScoreMsg msg) {

		if (msg.getModelType() != null && ModelType.checkAndGet(msg.getModelType()) == null) {
			throw new ParamException(ModelErrorCode.MODEL_TYPE_FORMAT_ERROR);
		}
		PageResult<PageDeviceScoreVo> pages = new PageResult<PageDeviceScoreVo>();
		PageResult<PageModelScoreVo> costPage = this.scoreDao.getPage(ModelType.OPTIMAL_COST, msg.getPageNo(),
				msg.getPageSize(), msg.getDeviceName(), msg.getDatacenterId(), PageModelScoreVo.class);
		PageResult<PageModelScoreVo> devicePage = this.scoreDao.getPage(ModelType.OPTIMAL_DEVICE, 1, 99999,
				msg.getDeviceName(), msg.getDatacenterId(), PageModelScoreVo.class);
		for (PageModelScoreVo costVo : costPage.getList()) {
			PageDeviceScoreVo vo = new PageDeviceScoreVo();
			vo.setCostScore(costVo.getTotalScore());
			vo.setDatacenterId(costVo.getDatacenterId());
			vo.setName(costVo.getName());
			vo.setId(costVo.getId());
			vo.setDatacenterName(this.assetService.detailDatacenter(costVo.getDatacenterId(), null).getName());
			vo.setIsolation(this.assetService.detailNode(costVo.getId(), "").getIsolation());
			vo.setEnergyEfficiencyRatio(this.assetService.detailNode(costVo.getId(), "").getEnergyEfficiencyRatio());

			for (PageModelScoreVo deviceVo : devicePage.getList()) {
				if (deviceVo.getId().equals(costVo.getId())) {
					vo.setDeviceScore(deviceVo.getTotalScore());
					break;
				}
			}

			boolean illness = false;
			if ((vo.getCostScore() != null && vo.getCostScore() < 60)
					|| (vo.getDeviceScore() != null && vo.getDeviceScore() < 60)) {
				illness = true;
			}
			if (msg.getIsIllness() != null && !msg.getIsIllness().equals(illness)) {
				continue;
			}

			if (msg.getIsolation() != null && vo.getIsolation() != null
					&& !msg.getIsolation().equals(vo.getIsolation())) {
				continue;
			}

			pages.getList().add(vo);
		}

		pages.setTotalCount(pages.getList().size());
		return pages;
	}

	public ModelBestPredictReplyMsg bestPredict(ModelBestPredictMsg msg) {
		ModelType mt = ModelType.checkAndGet(msg.getModelType());

		if (mt == null) {
			throw new ParamException(ModelErrorCode.MODEL_TYPE_FORMAT_ERROR);
		}

		List<ModelBestPredictVo> vos = factorDao.getByModelType(mt, ModelBestPredictVo.class);
		for (ModelBestPredictVo vo : vos) {
			vo.setUnit(MonitorMeter.getByMeter(vo.getFactorType()).getUnit());
		}

		ModelBestPredictReplyMsg reply = new ModelBestPredictReplyMsg();
		reply.setVos(vos);
		return reply;
	}
	/**
	 * zhangdp增加最优模型设置到用户模型中去
	 */
	
	public void updateBestPredictAndHistory(String type) {
		try {
			ModelType mt = ModelType.get(type);
			this.calculateModelTypeBestPredict(mt, true);
			factorDao.updateHistoryAndSample(type);
		} catch (Exception e) {
			log.error("更新迁移模型因子报错",e);
			e.printStackTrace();
		}
	}
	
	private boolean needSchedule(String resourceId, String type, Integer totalScore) {
		if(StringUtils.isBlank(resourceId) || StringUtils.isBlank(type)) {
			return false;
		}
		Double config = schedulerService.checkDataCenterNeedMigrate(resourceId, type);
		if(config != null && totalScore < config) {
			return true;
		}
		return false;
	}

	public List<DetailModelScoreReplyMsg> datacenterModelScore(@Valid DatacenterModelScoreMsg msg) {
		//查找出所有的数据中心
		//
		List<DetailModelScoreReplyMsg> list = new ArrayList<>();
		ListDatacenterMsg datamsg = new ListDatacenterMsg();
		List<DatacenterItemVo> datas = null;
		if(StringUtils.isNotBlank(msg.getDatacenterId())) {
			datas = new ArrayList<>();
			DatacenterItemVo vo = assetService.getDatacenter(msg.getDatacenterId());
			// vo.setId(msg.getDatacenterId());
			datas.add(vo);
		}else {
			datas =  assetService.listDatacenter(datamsg);
		}
		int mode = 0;
		List<DictModel> models = sysDictMapper.queryDictItemsByCode(DictCode.SCHEDULER_MODEL.getCode());
		if (models != null) {
			for (DictModel value : models) {
				mode = Integer.parseInt(value.getValue());
			}
		}
		ModelType type = ModelType.DATACENTER_COST;
		if(mode == 1) {
			type = ModelType.DATACENTER_DEVICE;
		}
		for(DatacenterItemVo vo : datas) {
			DetailModelScoreMsg detailmsg = new DetailModelScoreMsg();
			detailmsg.setResourceId(vo.getId());
			detailmsg.setModelType(type.name());
			DetailModelScoreReplyMsg dres = detailModelScore(detailmsg);
			dres.setResourceName(vo.getName());
			list.add(dres);
		}
		return list;
	}

	public AppDatacenterModelScoreVo appDatacenterModelScore(@Valid AppDatacenterModelScoreMsg msg) {
		AppDatacenterModelScoreVo vo = new AppDatacenterModelScoreVo();
		//查出所有数据中心最优设备评分
		PageModelScoreMsg costmsg = new PageModelScoreMsg();
		costmsg.setPageSize(1);
		costmsg.setModelType(ModelType.DATACENTER_COST.name());
		costmsg.setDatacenterId(msg.getDatacenterId());
		PageResult<PageModelScoreVo> costPage = pageModelScore(costmsg);
		if(costPage.getList() != null && !costPage.getList().isEmpty()) {
			vo.setDatacenterName(costPage.getList().get(0).getDatacenterName());
			vo.setDatacenterId(costPage.getList().get(0).getDatacenterId());
			vo.setCostTotalScore(costPage.getList().get(0).getTotalScore());
		}
		//查出应用最优评分
		//查出所有数据中心最优成本评分
		PageModelScoreMsg devicermsg = new PageModelScoreMsg();
		devicermsg.setPageSize(1);
		devicermsg.setDatacenterId(msg.getDatacenterId());
		devicermsg.setModelType(ModelType.DATACENTER_DEVICE.name());
		PageResult<PageModelScoreVo> devicePage = pageModelScore(devicermsg);
		if(devicePage.getList() != null && !devicePage.getList().isEmpty()) {
			vo.setDatacenterName(devicePage.getList().get(0).getDatacenterName());
			vo.setDatacenterId(devicePage.getList().get(0).getDatacenterId());
			vo.setDeviceTotalScore(devicePage.getList().get(0).getTotalScore());
		}
		//查出数据中心最优能耗
		PageModelScoreMsg powermsg = new PageModelScoreMsg();
		powermsg.setPageSize(1);
		powermsg.setDatacenterId(msg.getDatacenterId());
		powermsg.setModelType(ModelType.DATACENTER_POWER.name());
		PageResult<PageModelScoreVo> powerPage = pageModelScore(powermsg);
		if(powerPage.getList() != null && !powerPage.getList().isEmpty()) {
			vo.setDatacenterName(powerPage.getList().get(0).getDatacenterName());
			vo.setDatacenterId(powerPage.getList().get(0).getDatacenterId());
			vo.setPowerTotalScore(powerPage.getList().get(0).getTotalScore());
		}
		//查出数据中心最优配电子网
		PageModelScoreMsg eletricmsg = new PageModelScoreMsg();
		eletricmsg.setPageSize(1);
		eletricmsg.setDatacenterId(msg.getDatacenterId());
		eletricmsg.setModelType(ModelType.DATACENTER_ELECTRIC.name());
		PageResult<PageModelScoreVo> eletricPage = pageModelScore(powermsg);
		if(eletricPage.getList() != null && !eletricPage.getList().isEmpty()) {
			vo.setDatacenterName(eletricPage.getList().get(0).getDatacenterName());
			vo.setDatacenterId(eletricPage.getList().get(0).getDatacenterId());
			vo.setElectricTotalScore(eletricPage.getList().get(0).getTotalScore());
		}
		return vo;
	}

}
